<?php

/**
 * 微信支付分账
 */
class Sub_Ledger{//类定义开始

    // private $wx_api_key;    //微信商户平台设置的密钥key 32位
    private $mch_id;        //微信支付分配的商户号
    private $sub_mch_id;     //微信支付分配的子商户号
    private $appID;         //微信开放平台上的应用APPID
    private $nonce_str;     //随机字符串
	// private $cert_file = './cert/';
	// private $open_id = '';
    // private $notifyUrl = '';     //支付后的异步回调url
	// echo $_SESSION['Member_info'][0]['openid'];exit;
	public function __construct($openid){
        $this->mch_id = '1597722871';//微信服务商商户号
        $this->sub_mch_id = '1289698501';//支付收款商户号
        $this->appID = 'wx16320d7479a5774c';


        // $this->wx_api_key = 'fyh40082851514008285151400828515';
		// $this->open_id = $openid;
		// $this->cert_file = './cert/';
		// $this->notifyUrl = 'http://5p8.fyh5p8.com/xiaochengxu/WxPay_back.php';
    }
	/**
     * 微信服务商分账
     * @param string $merchant_num 特约商户商户号"
     * @param string $transaction_id 微信支付订单号
     * @param float $out_order_no 平台支付订单号
     * @param float $amount 金额
     * @return bool|mixed
     */
    public function SubmitJsApiUnifiedProfit($merchant_num){
        $unified_order_url = "https://api.mch.weixin.qq.com/secapi/pay/profitsharing";//统一下单地址
		$data = array(
            'mch_id'    => $this->mch_id,//服务商商户号
            'sub_mch_id'    => $merchant_num,//特约商户商户号
            'appID'    => $this->appID,
            'transaction_id' => '4200000593202007165995626581',//微信支付订单号
            'out_order_no' => '731594867401',//商户分账单号？暂时填写一个编号
            'nonce_str'     => getRandomString(32), //随机生成字符串
            'receivers' => array(
                'type'      => 'MERCHANT_ID',//MERCHANT_ID商户id
                'account'   => $this->sub_mch_id,//平台收款商户号
                'amount'    => 888,//分账金额
                'description'  => '分给商户A',//分账的原因描述
            )

		);
		$sign = $this->getSign($data);
		$data['sign'] = $sign;
        $xml = $this->arrayToXml($data);
        $resXml = $this->curl_POST($xml, $unified_order_url);
        return $this->xmlToArray($resXml);
    }

    //生成字母数字随机数
    public function getRandomString($len, $chars=null)
    {
        if (is_null($chars)){
            $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        }
        mt_srand(10000000*(double)microtime());
        for ($i = 0, $str = '', $lc = strlen($chars)-1; $i < $len; $i++){
            $str .= $chars[mt_rand(0, $lc)];
        }
        return $str;
    }

	/**
     * 对预支付参数签名，之后返回给网页
     * @param string $prepayID 预支付订单id
     * @return array
     */
    public function signJsApiPrepayParam($prepayID){
		$timeStamp = time();
		$data = array(
			"appId" => $this->appID,
			"timeStamp" => "$timeStamp",
			"nonceStr" => $this->createNonceStr(),
			"package" => "prepay_id=$prepayID",
			"signType" => "MD5",
		);
		$_this_sign = $this->getSign($data);
		$data['paySign'] = $_this_sign;
		return $data;
    }

	/**
     * 获取参数签名；
     * @param  Array  要传递的参数数组
     * @return String 通过计算得到的签名；
     */
    function getSign($params){
		foreach($params as $k => $v){
            $Parameters[$k] = $v;
        }
        //签名步骤一：按字典序排序参数
        ksort($Parameters);
        $String = $this->formatBizQueryParaMap($Parameters, false);
        //签名步骤二：在string后加入KEY
        $String = $String . "&key=" . $this->wx_api_key;
        //签名步骤三：MD5加密
        $String = md5($String);
        //签名步骤四：所有字符转为大写
        $result_ = strtoupper($String);
        return $result_;
    }

	/**
     * 数组转为xml
     * @param $arr
     * @return string
     */
    private function arrayToXml($arr){
        $xml = "<xml>";
        foreach($arr as $key => $val){
            if(is_numeric($val)){
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            }else{
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
            }
        }
        $xml .= "</xml>";
        return $xml;
    }

	/**
     * xml转为数组
     * @param $xml
     * @return mixed
     */
    public function xmlToArray($xml){
        return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    }

	/**
     * 生成指定位数的随机码
     * @param int $length
     * @return string
     */
    private function createNonceStr($length = 32){
		$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $charsLength = strlen($chars);
        $str = "";
        for($i = 0; $i < $length; $i++){
            $str .= substr($chars, rand(0, $charsLength - 1), 1);
        }
        return $str;
    }

	/**
     * 获取当前访问者的ip
     * @return array|false|string
     */
    private function get_client_ip(){
        if($_SERVER['REMOTE_ADDR']){
            $cip = $_SERVER['REMOTE_ADDR'];
        }elseif(getenv("REMOTE_ADDR")){
            $cip = getenv("REMOTE_ADDR");
        }elseif(getenv("HTTP_CLIENT_IP")){
            $cip = getenv("HTTP_CLIENT_IP");
        }else{
            $cip = "unknown";
        }
        return $cip;
    }

	/**
     * 格式化参数（签名过程需要）
     * @param array $paraMap
     * @param bool $urlencode 是否url编码
     * @return bool|string
     */
    public function formatBizQueryParaMap($paraMap, $urlencode){
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v) {
            if($k=="sign"){
                continue;
            }
            if($urlencode){
                $v = urlencode($v);
            }
            $buff .= $k . "=" . $v . "&";
        }
        $reqPar = false;
        if (strlen($buff) > 0) {
            $reqPar = substr($buff, 0, strlen($buff) - 1);
        }
        return $reqPar;
    }

	/**
     * POST提交
     * @param string $data 提交的数据
     * @param string $url 地址
     * @param int $second 超时时间
     * @return bool|mixed
     */
    private function curl_POST($data, $url, $second = 30){
        //初始化curl
        $ch = curl_init();
        //设置超时
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);
        //这里设置代理，如果有的话
        //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
        //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        //设置header
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        //post提交方式
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        //运行curl
        $res = curl_exec($ch);
        //返回结果
        if($res){
            curl_close($ch);
            return $res;
        }else{
            $error = curl_errno($ch);
            echo "curl出错，错误码:$error" . "<br>";
            curl_close($ch);
            return false;
        }
    }

	//需要使用证书的请求
	private function postXmlSSLCurl($data, $url, $second = 30){
		$ch = curl_init();
		//超时时间
		curl_setopt($ch,CURLOPT_TIMEOUT,$second);
		//这里设置代理，如果有的话
		//curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
		//curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
		curl_setopt($ch,CURLOPT_URL, $url);
		curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
		curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
		//设置header
		curl_setopt($ch,CURLOPT_HEADER,FALSE);
		//要求结果为字符串且输出到屏幕上
		curl_setopt($ch,CURLOPT_RETURNTRANSFER,TRUE);
		//设置证书
		//使用证书：cert 与 key 分别属于两个.pem文件
		//默认格式为PEM，可以注释
		curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
		curl_setopt($ch,CURLOPT_SSLCERT, $this->cert_file.'apiclient_cert.pem');
		//默认格式为PEM，可以注释
		curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
		curl_setopt($ch,CURLOPT_SSLKEY, $this->cert_file.'apiclient_key.pem');
		//post提交方式
		curl_setopt($ch,CURLOPT_POST, true);
		curl_setopt($ch,CURLOPT_POSTFIELDS, $data);
		$res = curl_exec($ch);
		//返回结果
		if($res){
			curl_close($ch);
			return $res;
		}
		else {
			$error = curl_errno($ch);
			echo "curl出错，错误码:$error"."<br>";
			curl_close($ch);
			return false;
		}
	}
}
